/*
 * PGN_Reader : A simple pgn reader for chess games.
 * Copyright (C) 2011 Laurent BERNABE
 * 
 * This program is free software: you can redistribute it and/or modify it under
 * the terms of the GNU General Public License as published by the Free Software
 * Foundation, either version 3 of the License, or (at your option) any later
 * version.
 * 
 * This program is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
 * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
 * details.
 * 
 * You should have received a copy of the GNU General Public License along with
 * this program. If not, see <http://www.gnu.org/licenses/>.
 */
package com.gmail.bernabe.laurent.java_swing.pgn_reader.processing;

import java.util.ArrayList;

import com.gmail.bernabe.laurent.java_swing.pgn_reader.gui.BoardJPanel;
import com.gmail.bernabe.laurent.java_swing.pgn_reader.gui.MovesJTextArea;
import com.gmail.bernabe.laurent.java_swing.pgn_reader.gui.PGNReaderFrame;
import com.gmail.bernabe.laurent.java_swing.pgn_reader.processing.move.BoardCell;
import com.gmail.bernabe.laurent.java_swing.pgn_reader.processing.piece.PawnStatus;
import com.gmail.bernabe.laurent.java_swing.pgn_reader.processing.piece.PieceForce;

/**
 * A "tape" storing all the half moves of the game,
 * and which can act on a Piece[][] (a board pieces values). 
 * @author laurent BERNABE
 *
 */
public class PlayingTape {
	
	public final static int WHITE = 0;
	public final static int BLACK = 1; 
	
	public PlayingTape(String pgnString, PGNReaderFrame pgnFrame){
		this.pgnFrame = pgnFrame;
		registerTheHalfMoves(pgnString);
		currentHalfMove = 0;
		playerTurn = 0;
		
		pawnStatus = new PawnStatus [2][8];
		for (int playerTurn = 0; playerTurn < 2; playerTurn++){
			int currentRow_FromWhiteSideStart = 5 - 2*playerTurn;
			for (int column = 0; column < 8; column++) {
				pawnStatus[playerTurn][column] = new PawnStatus(false, currentRow_FromWhiteSideStart);
			}
		}
	}
	
	public void forward(){
		if (currentHalfMove < halfMovesArray.length){
			processHalfMove(halfMovesArray[currentHalfMove]);
			currentHalfMove++;
			changePlayerTurn();
		}
	}
	
	public void backward(){
		if (currentHalfMove > 0) {
			currentHalfMove--;
			reverseHalfMove(halfMovesArray[currentHalfMove]);
			changePlayerTurn();
		}
	}
	
	/**
	 * Gets an array in order to know all pawn status.
	 * <br> 1st dimension is for white pawns.
	 * @return An array of array of PawnStatus.
	 */
	public PawnStatus [][] getPawnStatusClone(){
		return pawnStatus.clone();
	}
	
	private void changePlayerTurn(){
		playerTurn = 1 - playerTurn;
	}
	
	private void registerTheHalfMoves(String pgnString) {
		String [] pgnParts = pgnString.split("\\s+");
		ArrayList<String> halfMovesToStore = new ArrayList<String>(100);
		for (String currentPGNPart : pgnParts){
			boolean itIsAHalfMove = currentPGNPart.matches("^[a-zA-Z].*");
			if (itIsAHalfMove){
				halfMovesToStore.add(currentPGNPart);
			}
		}
		halfMovesArray = new String[halfMovesToStore.size()];
		halfMovesToStore.toArray(halfMovesArray);
	}

	private void processHalfMove(String halfMoveString) {
		BoardJPanel boardPanelPointer = pgnFrame.getGraphicPanel();
		MovesJTextArea movesDisplayer = pgnFrame.getTextArea();
		HalfMoveData halfMoveData = new HalfMoveData(halfMoveString);
		HalfMoveStartCellComputator startCellComputator = new HalfMoveStartCellComputator(halfMoveData, pgnFrame);
		
		if (halfMoveData.isLittleRoque()){
			if (playerTurn == WHITE){
				boardPanelPointer.animateThenRegister(new BoardCell(0, 4), new BoardCell(0, 6)); // animate king
				boardPanelPointer.animateThenRegister(new BoardCell(0, 7), new BoardCell(0, 5)); // animate queen side rook
			}
			else {
				boardPanelPointer.animateThenRegister(new BoardCell(7, 4), new BoardCell(7, 6)); // animate king
				boardPanelPointer.animateThenRegister(new BoardCell(7, 7), new BoardCell(7, 5)); // animate queen side rook
			}
		}
		else if (halfMoveData.isBigRoque()){
			if (playerTurn == WHITE){
				boardPanelPointer.animateThenRegister(new BoardCell(0, 4), new BoardCell(0, 2)); // animate king
				boardPanelPointer.animateThenRegister(new BoardCell(0, 0), new BoardCell(0, 3)); // animate king side rook
			}
			else {
				boardPanelPointer.animateThenRegister(new BoardCell(7, 4), new BoardCell(7, 2)); // animate king
				boardPanelPointer.animateThenRegister(new BoardCell(7, 0), new BoardCell(7, 3)); // animate king side rook
			}
		}
		else {
			
			BoardCell endCell = halfMoveData.getEndCell();
			int pawnColumn = endCell.cellColumn;
			
			BoardCell startCell = startCellComputator.startCell(playerTurn);
			boardPanelPointer.animateThenRegister(startCell, endCell);
			
			if (halfMoveData.movingPieceForce() == PieceForce.pawn) {
				pawnStatus[playerTurn][pawnColumn].hasEverPlayed = true;
			}
			
		}
		
		movesDisplayer.addHalfMove(halfMoveString);
	}
	
	private void reverseHalfMove(String halfMove) {
		MovesJTextArea movesDisplayer = pgnFrame.getTextArea();
		movesDisplayer.undoLastHalfMove();
	}
	
	private String [] halfMovesArray;
	private PGNReaderFrame pgnFrame;
	/**
	 * 1st dimension is for white pawns
	 */
	private PawnStatus [][] pawnStatus;
	/**
	 * 0 stands for white, 1 for black
	 */
	private int playerTurn;
	private int currentHalfMove;
	
}
